package com.liaowei.exception;

import cn.dev33.satoken.exception.NotLoginException;
import com.liaowei.common.BaseResponse;
import com.liaowei.common.Constants;
import com.liaowei.common.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 全局异常处理器
 */
@ControllerAdvice(annotations = {RestController.class, Controller.class})
//@RestControllerAdvice(annotations = {RestController.class, Controller.class})
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {


    /**
     * 进行异常处理方法
     * @return
     */
    @ExceptionHandler(CustomerException.class)
    public BaseResponse customerException(CustomerException ex){
        return ResultUtils.error(ex.getCode(),ex.getMessage(), ex.getDescription());
    }

    // 未登录异常 NotLoginException
    @ExceptionHandler(NotLoginException.class)
    public BaseResponse NotLoginExceptionException(NotLoginException e){
        return ResultUtils.error(Constants.NOT_LOGIN_ERROR, "未登录", "");
    }

    // 唯一约束异常 SQLIntegrityConstraintViolationException
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500
    public BaseResponse SQLIntegrityConstraintViolationExceptionHandler(SQLIntegrityConstraintViolationException e){
        String errorMessage = e.getMessage();
        String[] split = errorMessage.split(" ");
        String message = split[2] + "已存在";
        return ResultUtils.error(Constants.USERNAME_PASSWORD_ERROR, message, "");
    }

    //MethodArgumentNotValidException异常
    @ExceptionHandler(MethodArgumentNotValidException.class)//此方法捕获MethodArgumentNotValidException异常
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500
    public BaseResponse doMethodArgumentNotValidException(MethodArgumentNotValidException e) {

        BindingResult bindingResult = e.getBindingResult();
        //校验的错误信息
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        //收集错误
        StringBuffer errors = new StringBuffer();
        fieldErrors.forEach(error -> {
            errors.append(error.getDefaultMessage()).append(",");
        });
        return ResultUtils.error(Constants.USERNAME_PASSWORD_ERROR, errors.toString(), "");
    }

    // 不加 @RequestBody注解，校验失败抛出的则是 BindException
    @ExceptionHandler(BindException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500
    public BaseResponse bindExceptionHandler(BindException e){
        String messages = e.getBindingResult().getAllErrors()
                .stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining("；"));
        return ResultUtils.error(Constants.USERNAME_PASSWORD_ERROR, messages, "");
    }

    // @RequestParam 上校验失败后抛出的异常是 ConstraintViolationException
    @ExceptionHandler(ConstraintViolationException.class)
//    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)//状态码返回500
    public BaseResponse methodArgumentNotValid(ConstraintViolationException exception) {
        String message = exception.getConstraintViolations()
                .stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.joining("；"));
        return ResultUtils.error(Constants.USERNAME_PASSWORD_ERROR, message, "");
    }

}
